package com.winit.deploy.server;

import com.winit.common.util.JSONFileUtil;
import com.winit.common.util.ObjectToString;
import com.winit.core.server.PhpServer;
import com.winit.deploy.bean.WinitPhpInfo;
import com.winit.project.util.ProjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import java.util.Map;

/**
 * Created by wangjian on 16/10/17.
 */
public class WinitPhpServer extends PhpServer {

    private static Logger logger = LoggerFactory.getLogger(WinitPhpServer.class);

    private WinitPhpInfo phpInfo;

    public WinitPhpServer(String ip, String userName, Integer port,WinitPhpInfo phpInfo) throws Exception {
        super(ip, userName, port);
        this.phpInfo = phpInfo;
    }

    public WinitPhpInfo getPhpInfo() {
        return phpInfo;
    }

    /**
     * 推送结束后,校验临时目录下发布包是否存在
     * @throws Exception
     */
    public void doCheckPackage() throws Exception{

        String zipTempDir = this.phpInfo.getZipTempDir();
        String packageName = this.phpInfo.getPackageName();

        if(StringUtils.isEmpty(zipTempDir)
                ||StringUtils.isEmpty(packageName)){
            logger.error("WinitPhpServer:校验是否推送成功,参数存在空值."+ ObjectToString.getString(this.phpInfo));
            throw new Exception("校验是否推送成功,参数存在空值");
        }

        StringBuffer cmd = new StringBuffer();
        cmd.append("ls ").append(zipTempDir).append(" | grep ^").append(packageName).append(".zip$");
        this.initHandler();
        this.doExec(this.handler,cmd.toString());
        logger.info("WinitPhpServer:校验是否推送成功,返回:"+this.handler.getMessage());
        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:校验是否推送成功失败.返回:"+this.handler.getMessage());
            throw new Exception("校验是否推送成功失败."+this.handler.getMessage());
        }
        if(StringUtils.isEmpty(this.handler.getMessage())){
            logger.error("WinitPhpServer:校验是否推送成功,终端机推送包不存在.");
            throw new Exception("校验是否推送成功,终端机推送包不存在.");
        }
    }

    /**
     * 备份应用
     * 1.进入工程存放目录
     * 2.判断工程文件夹是否存在  存在继续  不存在退出
     * 3.将原工程打包至备份目录
     */
    public void doBakUp() throws Exception{

        String dirPath = this.phpInfo.getProjectDirPath();
        String dirName = this.phpInfo.getProjectDirName();
        String backUpPath = this.phpInfo.getBackUpPath();
        String trunkName = ProjectUtil.getTrunkProjectName(this.phpInfo.getProjectName());

        if(StringUtils.isEmpty(dirPath)
                || StringUtils.isEmpty(dirName)
                || StringUtils.isEmpty(backUpPath)){
            logger.error("WinitPhpServer:备份应用,参数存在空值."+ ObjectToString.getString(this.phpInfo));
            throw new Exception("备份应用,参数存在空值");
        }

        StringBuffer cmd = new StringBuffer();
//        cmd.append("ls ").append(dirPath).append(" | grep ^").append(dirName).append("$ && cd ").append(dirPath)
//                .append(" && tar -zcf ").append(backUpPath).append(" ").append(dirName);
        Map<String,String> proMap = JSONFileUtil.getFileJsonForBean(Thread.currentThread().getContextClassLoader().getResource("").getPath()
                + "data/php_bak.json", Map.class);
        String type = "default";
        if(proMap.containsKey(trunkName)){
            type = proMap.get(trunkName);
        }

//        if("tom".equalsIgnoreCase(trunkName)){
//            type = "tom";
//        }else if("eds".equalsIgnoreCase(trunkName)){
//            type = "eds";
//        }else if("help".equalsIgnoreCase(trunkName)){
//            type = "help";
//        }else if("sellerportal".equalsIgnoreCase(trunkName)){
//            type = "sellerportal";
//        }else if("jinxuan".equalsIgnoreCase(trunkName)){
//            type = "jinxuan";
//        }else if("booking".equalsIgnoreCase(trunkName)){
//            type = "booking";
//        }else if("TrackingWebsite".equalsIgnoreCase(trunkName)){
//            type = "tracking";
//        }else if("apiwebsite".equalsIgnoreCase(trunkName)){
//            type = "apiwebsite";
//        }else if("crm".equalsIgnoreCase(trunkName)){
//            type = "crm";
//        }

        cmd.append("source /etc/profile && cd /home/").append(this.phpInfo.getUserName()).append(" && sudo bash beetle_php_bak.sh ").append(type).append(" ").append(dirPath)
                .append(" ").append(dirName).append(" ").append(backUpPath).append(" && sudo chown beetle.beetle ").append(backUpPath);
        this.doExec(cmd.toString());

        //删除旧备份文件
        if(!StringUtils.isEmpty(this.phpInfo.getBackUpDir()) && !StringUtils.isEmpty(this.phpInfo.getPackageName())){
            cmd = new StringBuffer();
            cmd.append("source /etc/profile && cd ").append(this.phpInfo.getBackUpDir()).append(" && ls |grep ^").append(this.phpInfo.getPackageName())
                    .append("- && rm -rf `ls -t ").append(this.phpInfo.getPackageName()).append("-* | tail -n+4`");
            this.doExec(cmd.toString());
        }
    }

    /**
     * 拷贝工程
     * 1.进入工程存放目录
     * 2.判断工程文件夹是否存在  存在继续  不存在先创建再继续
     * 3.将war包拷贝至工程文件夹目录下并解压
     * 4.解压后删除war包
     */
    public boolean doInstall(String linuxUser) throws Exception{

        String dirPath = this.phpInfo.getProjectDirPath();
        String dirName = this.phpInfo.getProjectDirName();
        String zipTempDir = this.phpInfo.getZipTempDir();
        String packageName = this.phpInfo.getPackageName();

        if(StringUtils.isEmpty(dirPath)
                || StringUtils.isEmpty(dirName)
                || StringUtils.isEmpty(zipTempDir)
                || StringUtils.isEmpty(packageName)){
            logger.error("WinitPhpServer:安装程序,参数存在空值."+ ObjectToString.getString(this.phpInfo));
            throw new Exception("安装程序,参数存在空值");
        }
        this.initHandler();
        this.doExec(this.handler,"ls "+dirPath+" | grep ^"+dirName+"$");

        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:安装程序,查询工程目录是否存在失败.返回:"+this.handler.getMessage());
            throw new Exception("安装程序,查询工程目录是否存在失败."+this.handler.getMessage());
        }
        //目录不存在 先创建
        if(StringUtils.isEmpty(this.handler.getMessage())){
            this.initHandler();
            this.doExec(this.handler,"source /etc/profile && cd "+dirPath+" && sudo mkdir "+dirName);
            if(!this.handler.isSuccess()){
                logger.error("WinitPhpServer:安装程序,创建工程目录失败.返回:"+this.handler.getMessage());
                throw new Exception("安装程序,创建工程目录失败."+this.handler.getMessage());
            }
        }

        StringBuffer cmd = new StringBuffer();
        cmd.append("source /etc/profile && sudo chown ").append(linuxUser).append(".").append(linuxUser).append(" ")
                .append(zipTempDir).append("/").append(packageName)
                .append(".zip && sudo -u ").append(linuxUser).append(" cp ").append(zipTempDir).append("/").append(packageName).append(".zip ")
                .append(dirPath).append("/").append(dirName).append("/ && sudo rm -rf ").append(zipTempDir)
                .append("/").append(packageName).append(".zip && cd ").append(dirPath).append("/").append(dirName)
                .append(" && sudo -u ").append(linuxUser).append(" unzip -q -o ").append(packageName).append(".zip && sudo rm -rf ")
                .append(dirPath).append("/").append(dirName).append("/").append(packageName).append(".zip ");

        this.initHandler();
        this.doExec(this.handler,cmd.toString());

        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:安装程序失败.返回:"+this.handler.getMessage());
            throw new Exception("安装程序失败."+this.handler.getMessage());
        }
        return true;
    }

    /**
     * 回滚
     * 1.删除工程目录下的所有文件
     * 2.将备份的文件解压到工程目录下
     * @throws Exception
     */
    public void doRollBack(String linuxUser) throws Exception{

        String backUpPath = this.phpInfo.getBackUpPath();
        String dirPath = this.phpInfo.getProjectDirPath();
        String dirName = this.phpInfo.getProjectDirName();

        if(StringUtils.isEmpty(backUpPath)
                || StringUtils.isEmpty(dirName)
                || StringUtils.isEmpty(dirPath)){
            logger.error("WinitPhpServer:执行回滚,参数存在空值."+ ObjectToString.getString(this.phpInfo));
            throw new Exception("执行回滚,参数存在空值");
        }
        //1.判断回滚包是否存在
        this.initHandler();
        this.doExec(this.handler,"ls "+backUpPath);
        if( StringUtils.isEmpty(this.handler.getMessage())
                || this.handler.getMessage().indexOf("No such file or directory") != -1){
            throw new Exception("执行回滚,备份包不存在."+this.phpInfo.getBackUpPath());
        }

        StringBuffer cmd = new StringBuffer();
        if(this.phpInfo.isVmEnv()){
            cmd.append("tar -zxf ").append(this.phpInfo.getBackUpPath()).append(" -C ").append(dirPath).append("/ ");
        }else {
            cmd.append("source /etc/profile && sudo -u ").append(linuxUser).append(" tar --overwrite -zxf ").append(this.phpInfo.getBackUpPath()).append(" -C ").append(dirPath).append("/ ");
        }

        this.initHandler();
        this.doExec(this.handler,cmd.toString());

        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:代码回滚失败.返回:"+this.handler.getMessage());
            throw new Exception("代码回滚失败.返回:"+this.handler.getMessage());
        }
    }

    /**
     * 启动apache服务器
     * @throws Exception
     */
    public void doStartServer() throws Exception{
        this.initHandler();
        this.doExec(this.handler,"source /etc/profile && sudo service httpd start");
        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:启动apache服务器异常.返回:"+this.handler.getMessage());
            throw new Exception("启动apache服务器异常."+this.handler.getMessage());
        }
    }

    /**
     * 停止apache服务器
     * @throws Exception
     */
    public void doStopServer() throws Exception{
        this.initHandler();
        this.doExec(this.handler,"source /etc/profile && sudo service httpd stop");
        if(!this.handler.isSuccess()){
            logger.error("WinitPhpServer:停止apache服务器异常.返回:"+this.handler.getMessage());
            throw new Exception("停止apache服务器异常."+this.handler.getMessage());
        }
    }
}
